package com.castle.fortress.admin.orders.controller;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.castle.fortress.admin.core.constants.GlobalConstants;
import com.castle.fortress.admin.member.entity.MemberEntity;
import com.castle.fortress.admin.member.service.MemberService;
import com.castle.fortress.admin.orders.entity.SaleCouponDataEntity;
import com.castle.fortress.admin.orders.entity.SaleCouponEntity;
import com.castle.fortress.admin.orders.dto.SaleCouponDto;
import com.castle.fortress.admin.orders.enums.CouponSendTypeEnum;
import com.castle.fortress.admin.orders.service.SaleCouponDataService;
import com.castle.fortress.admin.orders.service.SaleCouponService;
import com.castle.fortress.admin.utils.BindApiUtils;
import com.castle.fortress.common.utils.ConvertUtil;
import com.castle.fortress.common.entity.RespBody;
import com.castle.fortress.common.exception.BizException;
import com.castle.fortress.common.respcode.GlobalRespCode;
import com.castle.fortress.common.enums.OperationTypeEnum;
import com.castle.fortress.admin.core.annotation.CastleLog;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import springfox.documentation.annotations.ApiIgnore;
import org.apache.logging.log4j.util.Strings;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import com.castle.fortress.admin.utils.ExcelUtils;

import javax.servlet.http.HttpServletResponse;

import com.castle.fortress.common.entity.DynamicExcelEntity;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * 优惠券 控制器
 *
 * @author whc
 * @since 2023-01-05
 */
@Api(tags = "优惠券管理控制器")
@Controller
public class SaleCouponController {
    @Autowired
    private SaleCouponService saleCouponService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private SaleCouponDataService saleCouponDataService;

    @Autowired
    private BindApiUtils bindApiUtils;

    /**
     * 优惠券的分页展示
     *
     * @param saleCouponDto 优惠券实体类
     * @param current       当前页
     * @param size          每页记录数
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.QUERY)
    @ApiOperation("优惠券分页展示")
    @GetMapping("/orders/saleCoupon/page")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:pageList")
    public RespBody<IPage<SaleCouponDto>> pageSaleCoupon(SaleCouponDto saleCouponDto, @RequestParam(required = false) Integer current, @RequestParam(required = false) Integer size) {
        Integer pageIndex = current == null ? GlobalConstants.DEFAULT_PAGE_INDEX : current;
        Integer pageSize = size == null ? GlobalConstants.DEFAULT_PAGE_SIZE : size;
        Page<SaleCouponDto> page = new Page(pageIndex, pageSize);
        IPage<SaleCouponDto> pages = saleCouponService.pageSaleCouponExtends(page, saleCouponDto);

        return RespBody.data(pages);
    }

    /**
     * 优惠券的列表展示
     *
     * @param saleCouponDto 优惠券实体类
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.QUERY)
    @ApiOperation("优惠券列表展示")
    @GetMapping("/orders/saleCoupon/list")
    @ResponseBody
    public RespBody<List<SaleCouponDto>> listSaleCoupon(SaleCouponDto saleCouponDto) {
        List<SaleCouponDto> list = saleCouponService.listSaleCoupon(saleCouponDto);
        return RespBody.data(list);
    }

    /**
     * 优惠券保存
     *
     * @param saleCouponDto 优惠券实体类
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.INSERT)
    @ApiOperation("优惠券保存")
    @PostMapping("/orders/saleCoupon/save")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:save")
    public RespBody<String> saveSaleCoupon(@RequestBody SaleCouponDto saleCouponDto) {
        if (saleCouponDto == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        SaleCouponEntity saleCouponEntity = ConvertUtil.transformObj(saleCouponDto, SaleCouponEntity.class);
        final JSONObject config = new JSONObject(bindApiUtils.getData("COUPON").getBindDetail());
        String prefix = config.getStr("url");

        if (saleCouponService.save(saleCouponEntity)) {
            saleCouponEntity.setGetUrl(prefix + "?id=" + saleCouponEntity.getId());
            saleCouponService.updateById(saleCouponEntity);
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 优惠券编辑
     *
     * @param saleCouponDto 优惠券实体类
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.UPDATE)
    @ApiOperation("优惠券编辑")
    @PostMapping("/orders/saleCoupon/edit")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:edit")
    public RespBody<String> updateSaleCoupon(@RequestBody SaleCouponDto saleCouponDto) {
        if (saleCouponDto == null || saleCouponDto.getId() == null || saleCouponDto.getId().equals(0L)) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        SaleCouponEntity saleCouponEntity = ConvertUtil.transformObj(saleCouponDto, SaleCouponEntity.class);
        if (saleCouponService.updateById(saleCouponEntity)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 优惠券删除
     *
     * @param id
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.DELETE)
    @ApiOperation("优惠券删除")
    @PostMapping("/orders/saleCoupon/delete")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:delete")
    public RespBody<String> deleteSaleCoupon(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (saleCouponService.removeById(id)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }


    /**
     * 优惠券批量删除
     *
     * @param ids
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.DELETE)
    @ApiOperation("优惠券批量删除")
    @PostMapping("/orders/saleCoupon/deleteBatch")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:deleteBatch")
    public RespBody<String> deleteSaleCouponBatch(@RequestBody List<Long> ids) {
        if (ids == null || ids.size() < 1) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        if (saleCouponService.removeByIds(ids)) {
            return RespBody.data("保存成功");
        } else {
            return RespBody.fail(GlobalRespCode.OPERATE_ERROR);
        }
    }

    /**
     * 优惠券详情
     *
     * @param id 优惠券id
     * @return
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.QUERY)
    @ApiOperation("优惠券详情")
    @GetMapping("/orders/saleCoupon/info")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:info")
    public RespBody<SaleCouponDto> infoSaleCoupon(@RequestParam Long id) {
        if (id == null) {
            throw new BizException(GlobalRespCode.PARAM_MISSED);
        }
        SaleCouponDto saleCouponDto = saleCouponService.getByIdExtends(id);

        return RespBody.data(saleCouponDto);
    }

    /**
     * 动态表头导出 依据展示的字段导出对应报表
     *
     * @param dynamicExcelEntity
     * @param response
     * @throws Exception
     */
    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.EXPORT)
    @PostMapping("/orders/saleCoupon/exportDynamic")
    @ApiOperation("动态表头导出，依据展示的字段导出对应报表")
    public void exportDynamic(@RequestBody DynamicExcelEntity<SaleCouponDto> dynamicExcelEntity, HttpServletResponse response) throws Exception {
        List<SaleCouponDto> list = saleCouponService.listSaleCoupon(dynamicExcelEntity.getDto());
        //字典、枚举、接口、json常量等转义后的列表数据 根据实际情况初始化该对象，null为list数据直接导出
        List<List<Object>> dataList = null;
        /**
         * 根据实际情况初始化dataList,可参照 com.castle.fortress.admin.system.controller.TmpDemoController类中方法：exportDynamic
         */
        ExcelUtils.exportDynamic(response, dynamicExcelEntity.getFileName() + ".xlsx", null, list, dynamicExcelEntity.getHeaderList(), dataList);
    }


    @CastleLog(operLocation = "优惠券", operType = OperationTypeEnum.OTHER)
    @ApiOperation("手动发送优惠券")
    @PostMapping("/orders/saleCoupon/send")
    @ResponseBody
    @RequiresPermissions("orders:saleCoupon:send")
    public RespBody<String> send(@RequestBody HashMap<String, Object> param) {
        System.out.println(param);
        if (param.get("couponId") == null) {
            throw new BizException("参数异常");
        }
        if (param.get("getNumber") == null) {
            throw new BizException("参数异常");
        }
        if (param.get("sendType") == null) {
            throw new BizException("参数异常");
        }
        String couponId = param.get("couponId").toString();
        SaleCouponEntity coupon = saleCouponService.getById(couponId);
        final Integer max = coupon.getGetMax(); //每人限领数量
        final Integer total = Integer.parseInt(coupon.getTotal()); //总计数量
        //验证券的数量是否足够
        Integer getNumber = Integer.parseInt(param.get("getNumber").toString());

        if (getNumber.compareTo(max) > 0) {
            throw new BizException("超出 每人限领:" + max + " 张");
        }
        Integer receiverCount = 0;
        final QueryWrapper<SaleCouponDataEntity> existsCountWrapper = new QueryWrapper<>();
        existsCountWrapper.eq("coupon_id", couponId);
        int existsCount = saleCouponDataService.count(existsCountWrapper);
        Integer sendType = Integer.parseInt(param.get("sendType").toString());
        List<MemberEntity> receivers = null;
        if (CouponSendTypeEnum.SEND_ALL.getCode().equals(sendType)) {
            //计算应该领取的用户数量 排除已经领取过的用户
            receivers = memberService.list();
            receiverCount = receivers.size();
        } else if (CouponSendTypeEnum.CHOICE_USER.getCode().equals(sendType)) {
            //根据用户id 查询应该发送的人数
            final Object receiverMember = param.get(CouponSendTypeEnum.CHOICE_USER.getDesc());
            if (receiverMember == null) {
                throw new BizException("参数异常");
            }
            final List<String> memberIds = Arrays.asList(receiverMember.toString().split(","));
            final QueryWrapper<MemberEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("id", memberIds);
            receivers = memberService.list(queryWrapper);
            receiverCount = receivers.size();
        } else if (CouponSendTypeEnum.CHOICE_USER_LEVEL.getCode().equals(sendType)) {
            final Object receiverMemberLevel = param.get(CouponSendTypeEnum.CHOICE_USER_LEVEL.getDesc());
            if (receiverMemberLevel == null) {
                throw new BizException("参数异常");
            }
            List<String> memberLevelIds = Arrays.asList(receiverMemberLevel.toString().split(","));
            QueryWrapper<MemberEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("level_id", memberLevelIds);
            receivers = memberService.list(queryWrapper);
            receiverCount = receivers.size();
            //根据用户等级查询用户id
            //根据用户id 以及券id 查询出应该发放的人数
        } else {
            throw new BizException("参数异常");
        }
        if ((receiverCount - existsCount) * getNumber > total) {
            throw new BizException("超出总数限制");
        }

//        走正常的发送流程
        saleCouponDataService.send(coupon, getNumber, receivers);
        return RespBody.data("保存成功");
    }
}
